Skip to content

Conversation

@wleroux
Copy link
Contributor

@wleroux wleroux commented Feb 10, 2019

No description provided.

@wleroux
Copy link
Contributor Author

wleroux commented Feb 10, 2019

While I've added tests to validate this, I have not manually tested it using an actual server.

The reason I want SSE is for security reasons. WebSockets are surprisingly difficult to get working with existing infrastructure (i.e.: CSRF/CORS) and skip all of the request filters that sets up the Authentication. With SSE, this is all free (since we're using HTTP.)

There's a couple contentious points I'd like to investigate further as well. While this should work as-is when asyncServletModeEnabled = false, I believe that the subscriptions would be prematurely completed when asyncServletModeEnabled = true as the code executes asyncContext.completed() on the finally clause in AbstractGraphQLHttpServlet#doRequest.

Anyhow, I thought I'd put this up for now. Will manually test + inspect the aforementioned issue tomorrow.

@wleroux
Copy link
Contributor Author

wleroux commented Feb 10, 2019

It works! Manually tested this using my application. In my situation, I needed to verify that it works with CSRF-TOKEN, CORS, Authentication as well (the reason I looked into SSE in the first place.)

Additional notes: SSE only supports GET method. POST is not natively supported by EventSource. Some people may prefer a custom POST approach to prevent authentication information to leak into logs.

Here's an example of usage:

Spring Boot Controller

@Component
class EchoController: GraphQLSubscriptionResolver {
    fun echo(arg: String): Publisher<String> {
        return Mono.just(arg)
    }
}

Schema Definition

type Subscription {
    echo(arg: String!): String!
}

JavaScript Client

import gql from "graphql-tag";

var subscriptionQuery = gql`subscription {
    echo(arg: "Hello, World!")
}`;

var eventSource = new EventSource("/graphql?query=" + encodeURIComponent(subscriptionQuery.loc.source.body));
eventSource.onmessage = message => console.log(JSON.parse(message.data).data.echo);

@wleroux
Copy link
Contributor Author

wleroux commented Feb 11, 2019

I've added the configuration for the timeout of the subscription as any value is arbitrary; the previous setting of 1 minute was too short for me. The default value (0) will allow the subscription to live indefinitely... But if that's not desirable, it can be overridden.

The asyncModeEnabled=true did cause problems with subscriptions; the latest commit fixes that issue.

@wleroux
Copy link
Contributor Author

wleroux commented Feb 15, 2019

@oliemansm Any hope on this making it in?

@oliemansm
Copy link
Member

@wleroux Thanks a lot for this!!

@oliemansm oliemansm merged commit 673e9eb into graphql-java-kickstart:master Feb 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants